package bbs.controller;

import bbs.annotation.GlobalInterceptor;
import bbs.annotation.VerifyParam;
import bbs.controller.base.ABaseController;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import bbs.entity.config.WebConfig;
import bbs.entity.constants.Constants;
import bbs.entity.dto.SessionWebUserDto;
import bbs.entity.enums.*;
import bbs.entity.po.*;
import bbs.entity.query.ForumArticleAttachmentQuery;
import bbs.entity.query.ForumArticleQuery;
import bbs.entity.vo.PaginationResultVO;
import bbs.entity.vo.ResponseVO;
import bbs.entity.vo.web.FormArticleDetailVO;
import bbs.entity.vo.web.FormArticleUpdateDetailVO;
import bbs.entity.vo.web.ForumArticleAttachmentVo;
import bbs.entity.vo.web.ForumArticleVO;
import bbs.exception.BusinessException;
import bbs.service.*;
import bbs.utils.CopyTools;
import bbs.utils.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;


@RestController("forumArticleController")
@RequestMapping({"/forum"})
public class ForumArticleController extends ABaseController {
    private static final Logger logger = LoggerFactory.getLogger(ForumArticleController.class);

    @Resource
    private WebConfig webConfig;

    @Resource
    private ForumBoardService forumBoardService;

    @Resource
    private ForumArticleService forumArticleService;

    @Resource
    private ForumArticleAttachmentService forumArticleAttachmentService;

    @Resource
    private ForumArticleAttachmentDownloadService forumArticleAttachmentDownloadService;

    @Resource
    private LikeRecordService likeRecordService;

    @Resource
    private UserInfoService userInfoService;



    @RequestMapping({"/loadArticle"})
    public ResponseVO loadArticle(HttpSession session, Integer boardId, Integer pBoardId, Integer orderType, Integer pageNo) {
        ForumArticleQuery forumArticleQuery = new ForumArticleQuery();
        forumArticleQuery.setBoardId((boardId == null || boardId == 0) ? null : boardId);
        forumArticleQuery.setpBoardId(pBoardId);
        forumArticleQuery.setPageNo(pageNo);
        SessionWebUserDto userDto = getUserInfoFromSession(session);
        if (userDto != null) {
            forumArticleQuery.setCurrentUserId(userDto.getUserId());
        } else {
            forumArticleQuery.setStatus(ArticleStatusEnum.AUDIT.getStatus());
        }

        ArticleOrderTypeEnum articleOrderTypeEnum = ArticleOrderTypeEnum.getByType(orderType);
        articleOrderTypeEnum = (articleOrderTypeEnum == null) ? ArticleOrderTypeEnum.HOT : articleOrderTypeEnum;
        forumArticleQuery.setOrderBy(articleOrderTypeEnum.getOrderSql());
        PaginationResultVO paginationResultVO = this.forumArticleService.findListByPage(forumArticleQuery);
        return getSuccessResponseVO(convert2PaginationVO(paginationResultVO, ForumArticleVO.class));
    }

    @RequestMapping({"/loadBoard4Post"})
    @GlobalInterceptor(checkLogin = true)
    public ResponseVO loadBoard4Post(HttpSession session) {
        SessionWebUserDto userDto = getUserInfoFromSession(session);
        Integer integer = null;
        if (!userDto.getIsAdmin().booleanValue())
            integer = Constants.ONE;
        return getSuccessResponseVO(this.forumBoardService.getBoardTree(integer));
    }

    @RequestMapping({"/postArticle"})
    @GlobalInterceptor(checkLogin = true, checkParams = true, frequencyType = UserOperFrequencyTypeEnum.POST_ARTICLE)
    public ResponseVO postArticle(
            HttpSession session,
            MultipartFile cover,
            MultipartFile attachment,
            Integer integral,
            @VerifyParam(required = true) Integer pBoardId,
            Integer boardId,
            @VerifyParam(required = true, max = 150) String title,
            @VerifyParam String content,
            String markdownContent,
            @VerifyParam(required = true) Integer editorType,
            @VerifyParam(max = 200) String summary)
    {
        title = StringTools.eecpapeHtml(title);
        SessionWebUserDto userDto = getUserInfoFromSession(session);
//        设置用户名
        userDto.setNickName(userInfoService.getUserInfoByUserId(userDto.getUserId()).getNickName());

        ForumArticle forumArticle = new ForumArticle();
        forumArticle.setpBoardId(pBoardId);
        forumArticle.setBoardId(boardId);
        forumArticle.setTitle(title);
        forumArticle.setContent(content);
        if (EditTypeEnum.MARKDOWN.getType().equals(editorType) && StringTools.isEmpty(markdownContent))
            throw new BusinessException(ResponseCodeEnum.CODE_600);

        forumArticle.setMarkdownContent(markdownContent);
        forumArticle.setEditorType(editorType);
        forumArticle.setSummary(summary);
        forumArticle.setUserId(userDto.getUserId());
        forumArticle.setNickName(userDto.getNickName());
        forumArticle.setUserIpAddress(userDto.getProvince());

        //   附件信息
        ForumArticleAttachment forumArticleAttachment = new ForumArticleAttachment();
        forumArticleAttachment.setIntegral((integral == null) ? 0 : integral);
        this.forumArticleService.postArticle(userDto.getIsAdmin(), forumArticle, forumArticleAttachment, cover, attachment);
        return getSuccessResponseVO(forumArticle.getArticleId());
    }

    /**
     * 获取文章信息
     * @param session
     * @param articleId
     * @return
     */
    @RequestMapping({"/getArticleDetail"})
    public ResponseVO getArticleDetail(HttpSession session, String articleId) {
        SessionWebUserDto sessionWebUserDto = getUserInfoFromSession(session);
        ForumArticle forumArticle = forumArticleService.readArticle(articleId);
        if (
                forumArticle == null ||
                    (ArticleStatusEnum.NO_AUDIT.getStatus().equals(forumArticle.getStatus())
                            && (sessionWebUserDto == null || !sessionWebUserDto.getUserId().equals(forumArticle.getUserId())
                            && !sessionWebUserDto.getIsAdmin()))
                        || ArticleStatusEnum.DEL.getStatus().equals(forumArticle.getStatus())
        ){
            throw new BusinessException(ResponseCodeEnum.CODE_404);
        }

        FormArticleDetailVO formArticleDetailVO = new FormArticleDetailVO();
        formArticleDetailVO.setForumArticle((ForumArticleVO) CopyTools.copy(forumArticle, ForumArticleVO.class));
//        判断是否上传附件
        if (forumArticle.getAttachmentType().equals(Constants.ONE)) {
            ForumArticleAttachmentQuery forumArticleAttachmentQuery = new ForumArticleAttachmentQuery();
            forumArticleAttachmentQuery.setArticleId(forumArticle.getArticleId());
            List list = this.forumArticleAttachmentService.findListByParam(forumArticleAttachmentQuery);
            if (!list.isEmpty())
                formArticleDetailVO.setAttachment((ForumArticleAttachmentVo)CopyTools.copy(list.get(0), ForumArticleAttachmentVo.class));
        }
//        判断是否点赞
        if (sessionWebUserDto != null) {
            LikeRecord likeRecord = this.likeRecordService.getLikeRecordByObjectIdAndUserIdAndOpType(articleId, sessionWebUserDto.getUserId(), OperRecordOpTypeEnum.ARTICLE_LIKE
                    .getType());
            if (likeRecord != null)
                formArticleDetailVO.setHaveLike(Boolean.TRUE);
        }
        //        判断是否收藏
        if (sessionWebUserDto != null) {
            LikeRecord likeRecord = this.likeRecordService.getLikeRecordByObjectIdAndUserIdAndOpType(articleId, sessionWebUserDto.getUserId(), OperRecordOpTypeEnum.ARTICLE_LIKE
                    .getType());
            if (likeRecord != null)
                formArticleDetailVO.setHaveLike(Boolean.TRUE);
        }
        return getSuccessResponseVO(formArticleDetailVO);
    }

    /**
     * 文章&评论 点赞
     * @param session
     * @param articleId
     * @return
     */
    @RequestMapping({"/doLike"})
    @GlobalInterceptor(checkLogin = true, checkParams = true)
    public ResponseVO doLike(HttpSession session, @VerifyParam(required = true) String articleId) {
        String userUserId = getUserInfoFromSession(session).getUserId();
        String nickName = userInfoService.getUserInfoByUserId(userUserId).getNickName();

        this.likeRecordService.doLike(articleId, userUserId, nickName, OperRecordOpTypeEnum.ARTICLE_LIKE.ARTICLE_LIKE);
        return getSuccessResponseVO(null);
    }


    @RequestMapping({"/getUserDownloadInfo"})
    @GlobalInterceptor(checkLogin = true, checkParams = true)
    public ResponseVO getUserDownloadInfo(HttpSession session, @VerifyParam(required = true) String fileId) {
        UserInfo userInfo = this.userInfoService.getUserInfoByUserId(getUserInfoFromSession(session).getUserId());
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put("userIntegral", userInfo.getCurrentIntegral());
        ForumArticleAttachmentDownload forumArticleAttachmentDownload = this.forumArticleAttachmentDownloadService.getForumArticleAttachmentDownloadByFileIdAndUserId(fileId,
                getUserInfoFromSession(session).getUserId());
        hashMap.put("haveDownload", Boolean.valueOf((forumArticleAttachmentDownload != null)));
        return getSuccessResponseVO(hashMap);
    }

    /**
     * 附件下载
     * @param session
     * @param request
     * @param response
     * @param fileId
     */
    @RequestMapping({"/attachmentDownload"})
    @GlobalInterceptor(checkLogin = true, checkParams = true)
    public void attachmentDownload(HttpSession session, HttpServletRequest request, HttpServletResponse response, @VerifyParam(required = true) String fileId) {
        ForumArticleAttachment forumArticleAttachment = this.forumArticleAttachmentService.downloadAttachment(fileId, getUserInfoFromSession(session));
        FileInputStream fileInputStream = null;
        ServletOutputStream servletOutputStream = null;
        String downloadFileName = forumArticleAttachment.getFileName();
        String filePath = this.webConfig.getProjectFolder() + "/file/" + "attachment/" + forumArticleAttachment.getFilePath();
        File file = new File(filePath);
        try {
            fileInputStream = new FileInputStream(file);
            servletOutputStream = response.getOutputStream();
            response.setContentType("application/x-msdownload; charset=UTF-8");
            if (request.getHeader("User-Agent").toLowerCase().indexOf("msie") > 0) {
                downloadFileName = URLEncoder.encode(downloadFileName, "UTF-8");
            } else {
                downloadFileName = new String(downloadFileName.getBytes("UTF-8"), "ISO8859-1");
            }
            response.setHeader("Content-Disposition", "attachment;filename=\"" + downloadFileName + "\"");
            byte[] arrayOfByte = new byte[1024];
            int len = 0;
            while ((len = fileInputStream.read(arrayOfByte)) != -1)
                servletOutputStream.write(arrayOfByte, 0, len);
            servletOutputStream.flush();
        } catch (Exception exception) {
            logger.error("下载异常", exception);
            throw new BusinessException("下载失败");
        } finally {
            try {
                if (fileInputStream != null)
                    fileInputStream.close();
            } catch (IOException iOException) {
                logger.error("IO异常", iOException);
            }
            try {
                if (servletOutputStream != null)
                    servletOutputStream.close();
            } catch (IOException iOException) {
                logger.error("IO异常", iOException);
            }
        }
    }

    @RequestMapping({"/articleDetail4Update"})
    @GlobalInterceptor(checkLogin = true, checkParams = true)
    public ResponseVO articleDetail4Update(HttpSession session, @VerifyParam(required = true) String articleId) {
        SessionWebUserDto userDto = getUserInfoFromSession(session);
        ForumArticle forumArticle = this.forumArticleService.getForumArticleByArticleId(articleId);
        if (forumArticle == null || !forumArticle.getUserId().equals(userDto.getUserId()))
            throw new BusinessException("帖子不存在或您无权编辑该帖子");

        FormArticleUpdateDetailVO formArticleUpdateDetailVO = new FormArticleUpdateDetailVO();
        formArticleUpdateDetailVO.setForumArticle(forumArticle);
        if (forumArticle.getAttachmentType() == 1) {
            ForumArticleAttachmentQuery forumArticleAttachmentQuery = new ForumArticleAttachmentQuery();
            forumArticleAttachmentQuery.setArticleId(forumArticle.getArticleId());
            List<ForumArticleAttachment> list = this.forumArticleAttachmentService.findListByParam(forumArticleAttachmentQuery);
            if (!list.isEmpty())
                formArticleUpdateDetailVO.setAttachment((ForumArticleAttachmentVo)CopyTools.copy(list.get(0), ForumArticleAttachmentVo.class));
        }
        return getSuccessResponseVO(formArticleUpdateDetailVO);
    }

    @RequestMapping({"/updateArticle"})
    @GlobalInterceptor(checkLogin = true, checkParams = true)
    public ResponseVO updateArticle(HttpSession session, MultipartFile cover, MultipartFile attachment, Integer integral, @VerifyParam(required = true) String articleId, @VerifyParam(required = true) Integer pBoardId, Integer boardId, @VerifyParam(required = true, max = 150) String title, @VerifyParam(required = true) String content, String markdownContent, @VerifyParam(required = true) Integer editorType, @VerifyParam(max = 200) String summary, @VerifyParam(required = true) Integer attachmentType) {
        title = StringTools.eecpapeHtml(title);
        SessionWebUserDto userDto = getUserInfoFromSession(session);
        ForumArticle forumArticle = new ForumArticle();
        forumArticle.setArticleId(articleId);
        forumArticle.setpBoardId(pBoardId);
        forumArticle.setBoardId(boardId);
        forumArticle.setTitle(title);
        forumArticle.setContent(content);
        forumArticle.setMarkdownContent(markdownContent);
        forumArticle.setEditorType(editorType);
        forumArticle.setSummary(summary);
        forumArticle.setUserIpAddress(userDto.getProvince());
        forumArticle.setAttachmentType(attachmentType);
        forumArticle.setUserId(userDto.getUserId());
        ForumArticleAttachment forumArticleAttachment = new ForumArticleAttachment();
        forumArticleAttachment.setIntegral((integral == null) ? 0 : integral);
        this.forumArticleService.updateArticle(userDto.getIsAdmin(), forumArticle, forumArticleAttachment, cover, attachment);
        return getSuccessResponseVO(forumArticle.getArticleId());
    }

    @RequestMapping({"/search"})
    @GlobalInterceptor(checkParams = true)
    public ResponseVO updateArticle(@VerifyParam(required = true, min = 1) String keyword) {
        ForumArticleQuery forumArticleQuery = new ForumArticleQuery();
        forumArticleQuery.setTitleFuzzy(keyword);
        PaginationResultVO paginationResultVO = forumArticleService.findListByPage(forumArticleQuery);
        return getSuccessResponseVO(paginationResultVO);
    }

}
